<template>
  <div :class="`${prefixCls}`">
    <div class="content">
      <a-tabs :size="`small`" v-model:activeKey="activeKey">
        <a-tab-pane tab="秒" key="second" v-if="!hideSecond">
          <SecondUI v-model:value="second" :disabled="disabled"/>
        </a-tab-pane>
        <a-tab-pane tab="分" key="minute">
          <MinuteUI v-model:value="minute" :disabled="disabled"/>
        </a-tab-pane>
        <a-tab-pane tab="时" key="hour">
          <HourUI v-model:value="hour" :disabled="disabled"/>
        </a-tab-pane>
        <a-tab-pane tab="日" key="day">
          <DayUI v-model:value="day" :week="week" :disabled="disabled"/>
        </a-tab-pane>
        <a-tab-pane tab="月" key="month">
          <MonthUI v-model:value="month" :disabled="disabled"/>
        </a-tab-pane>
        <a-tab-pane tab="周" key="week">
          <WeekUI v-model:value="week" :day="day" :disabled="disabled"/>
        </a-tab-pane>
        <a-tab-pane tab="年" key="year" v-if="!hideYear && !hideSecond">
          <YearUI v-model:value="year" :disabled="disabled"/>
        </a-tab-pane>
      </a-tabs>
      <a-divider/>
      <!-- 执行时间预览 -->
      <a-row :gutter="8">
        <a-col :span="18" style="margin-top: 22px;">
          <a-row :gutter="8">
            <a-col :span="8" style="margin-bottom: 12px;">
              <a-input v-model:value="inputValues.second" @blur="onInputBlur">
                <template #addonBefore>
                  <span class="allow-click" @click="activeKey='second'">秒</span>
                </template>
              </a-input>
            </a-col>
            <a-col :span="8" style="margin-bottom: 12px;">
              <a-input v-model:value="inputValues.minute" @blur="onInputBlur">
                <template #addonBefore>
                  <span class="allow-click" @click="activeKey='minute'">分</span>
                </template>
              </a-input>
            </a-col>
            <a-col :span="8" style="margin-bottom: 12px;">
              <a-input v-model:value="inputValues.hour" @blur="onInputBlur">
                <template #addonBefore>
                  <span class="allow-click" @click="activeKey='hour'">时</span>
                </template>
              </a-input>
            </a-col>
            <a-col :span="8" style="margin-bottom: 12px;">
              <a-input v-model:value="inputValues.day" @blur="onInputBlur">
                <template #addonBefore>
                  <span class="allow-click" @click="activeKey='day'">日</span>
                </template>
              </a-input>
            </a-col>
            <a-col :span="8" style="margin-bottom: 12px;">
              <a-input v-model:value="inputValues.month" @blur="onInputBlur">
                <template #addonBefore>
                  <span class="allow-click" @click="activeKey='month'">月</span>
                </template>
              </a-input>
            </a-col>
            <a-col :span="8" style="margin-bottom: 12px;">
              <a-input v-model:value="inputValues.week" @blur="onInputBlur">
                <template #addonBefore>
                  <span class="allow-click" @click="activeKey='week'">周</span>
                </template>
              </a-input>
            </a-col>
            <a-col :span="8">
              <a-input v-model:value="inputValues.year" @blur="onInputBlur">
                <template #addonBefore>
                  <span class="allow-click" @click="activeKey='year'">年</span>
                </template>
              </a-input>
            </a-col>
            <a-col :span="16">
              <a-input v-model:value="inputValues.cron" @blur="onInputCronBlur">
                <template #addonBefore>
                  <a-tooltip title="Cron表达式">式</a-tooltip>
                </template>
              </a-input>
            </a-col>
          </a-row>
        </a-col>
        <a-col :span="6">
          <div>近十次执行时间（不含年）</div>
          <a-textarea type="textarea" :value="preTimeList" :rows="5"/>
        </a-col>
      </a-row>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { computed, reactive, ref, watch, provide } from 'vue'
import { useDesign } from '/@/hooks/web/useDesign'
import CronParser from 'cron-parser'
import SecondUI from './tabs/SecondUI.vue'
import MinuteUI from './tabs/MinuteUI.vue'
import HourUI from './tabs/HourUI.vue'
import DayUI from './tabs/DayUI.vue'
import MonthUI from './tabs/MonthUI.vue'
import WeekUI from './tabs/WeekUI.vue'
import YearUI from './tabs/YearUI.vue'
import { cronEmits, cronProps } from './easy.cron.data'
import { dateFormat, simpleDebounce } from '/@/utils/common/compUtils'

const { prefixCls } = useDesign('easy-cron-inner')
provide('prefixCls', prefixCls)
const emit = defineEmits([...cronEmits])
const props = defineProps({ ...cronProps })
const activeKey = ref(props.hideSecond ? 'minute' : 'second')
const second = ref('*')
const minute = ref('*')
const hour = ref('*')
const day = ref('*')
const month = ref('*')
const week = ref('?')
const year = ref('*')
const inputValues = reactive({ second: '', minute: '', hour: '', day: '', month: '', week: '', year: '', cron: '' })
const preTimeList = ref('执行预览，会忽略年份参数。')

// cron表达式
const cronValueInner = computed(() => {
  let result: string[] = []
  if (!props.hideSecond) {
    result.push(second.value ? second.value : '*')
  }
  result.push(minute.value ? minute.value : '*')
  result.push(hour.value ? hour.value : '*')
  result.push(day.value ? day.value : '*')
  result.push(month.value ? month.value : '*')
  result.push(week.value ? week.value : '?')
  if (!props.hideYear && !props.hideSecond) result.push(year.value ? year.value : '*')
  return result.join(' ')
})
// 不含年
const cronValueNoYear = computed(() => {
  const v = cronValueInner.value
  if (props.hideYear || props.hideSecond) return v
  const vs = v.split(' ')
  if (vs.length >= 6) {
    // 转成 Quartz 的规则
    vs[5] = convertWeekToQuartz(vs[5])
  }
  return vs.slice(0, vs.length - 1).join(' ')
})
const calTriggerList = simpleDebounce(calTriggerListInner, 500)

watch(() => props.value, (newVal) => {
  if (newVal === cronValueInner.value) {
    return
  }
  formatValue()
})


watch(cronValueInner, (newValue) => {
  calTriggerList()
  emitValue(newValue)
  assignInput()
})

// watch(minute, () => {
//   if (second.value === '*') {
//     second.value = '0'
//   }
// })
// watch(hour, () => {
//   if (minute.value === '*') {
//     minute.value = '0'
//   }
// })
// watch(day, () => {
//   if (day.value !== '?' && hour.value === '*') {
//     hour.value = '0'
//   }
// })
// watch(week, () => {
//   if (week.value !== '?' && hour.value === '*') {
//     hour.value = '0'
//   }
// })
// watch(month, () => {
//   if (day.value === '?' && week.value === '*') {
//     week.value = '1'
//   } else if (week.value === '?' && day.value === '*') {
//     day.value = '1'
//   }
// })
// watch(year, () => {
//   if (month.value === '*') {
//     month.value = '1'
//   }
// })

assignInput()
formatValue()
calTriggerListInner()

function assignInput() {
  inputValues.second = second.value
  inputValues.minute = minute.value
  inputValues.hour = hour.value
  inputValues.day = day.value
  inputValues.month = month.value
  inputValues.week = week.value
  inputValues.year = year.value
  inputValues.cron = cronValueInner.value
}

function formatValue() {
  if (!props.value) return
  const values = props.value.split(' ').filter(item => !!item)
  if (!values || values.length <= 0) return
  let i = 0
  if (!props.hideSecond) second.value = values[i++]
  if (values.length > i) minute.value = values[i++]
  if (values.length > i) hour.value = values[i++]
  if (values.length > i) day.value = values[i++]
  if (values.length > i) month.value = values[i++]
  if (values.length > i) week.value = values[i++]
  if (values.length > i) year.value = values[i]
  assignInput()
}

// Quartz 的规则：
// 1 = 周日，2 = 周一，3 = 周二，4 = 周三，5 = 周四，6 = 周五，7 = 周六
function convertWeekToQuartz(week: string) {
  let convert = (v: string) => {
    if (v === '0') {
      return '1'
    }
    if (v === '1') {
      return '0'
    }
    return (Number.parseInt(v) - 1).toString()
  }
  // 匹配示例 1-7 or 1/7
  let patten1 = /^([0-7])([-/])([0-7])$/
  // 匹配示例 1,4,7
  let patten2 = /^([0-7])(,[0-7])+$/
  if (/^[0-7]$/.test(week)) {
    return convert(week)
  } else if (patten1.test(week)) {
    return week.replace(patten1, ($0, before, separator, after) => {
      if (separator === '/') {
        return convert(before) + separator + after
      } else {
        return convert(before) + separator + convert(after)
      }
    })
  } else if (patten2.test(week)) {
    return week.split(',').map(v => convert(v)).join(',')
  }
  return week
}

function calTriggerListInner() {
  // 设置了回调函数
  if (props.remote) {
    props.remote(cronValueInner.value, +new Date(), v => {
      preTimeList.value = v
    })
    return
  }
  const format = 'yyyy-MM-dd hh:mm:ss'
  const options = {
    currentDate: dateFormat(new Date(), format),
  }
  const iter = CronParser.parseExpression(cronValueNoYear.value, options)
  const result: string[] = []
  for (let i = 1; i <= 10; i++) {
    result.push(dateFormat(new Date(iter.next() as any), format))
  }
  preTimeList.value = result.length > 0 ? result.join('\n') : '无执行时间'
}

function onInputBlur() {
  second.value = inputValues.second
  minute.value = inputValues.minute
  hour.value = inputValues.hour
  day.value = inputValues.day
  month.value = inputValues.month
  week.value = inputValues.week
  year.value = inputValues.year
}

function onInputCronBlur(event) {
  emitValue(event.target.value)
}

function emitValue(value) {
  emit('change', value)
  emit('update:value', value)
}
</script>
<style lang="less">
@import "easy.cron.inner";
</style>